package com.ruoyi.system.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service.OssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @description: OSS上传服务实现
 * @author: Marvin
 * @create: 2025-01-01 10:31
 */
@Service
public class OssServiceImpl implements OssService {
    private static final Logger logger = LoggerFactory.getLogger(OssServiceImpl.class);

    @Autowired
    private OSS ossClient;

    @Value("${oss.bucketName}")
    private String bucketName;
    @Value("${oss.endpoint}")
    private String endpoint;
    @Value("${oss.accessKeyId}")
    private String accessId;
    @Value("${oss.ossAddrs}")
    private String ossAddrs;

    @Override
    public AjaxResult getPolicy() {
        // 拼接出Host地址
        String host = "https://" + bucketName + "." + endpoint;

        Map<String, String> respMap = null;
        try {
            // 设置过期时间: 秒数，这里设置10秒就过期
            long expireTime = 10;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);

            /// 指定请求的条件
            PolicyConditions policyConditions = new PolicyConditions();
            // 设置内容长度允许的字节数，最大是1048576000个字节，1MB=1048576个字节，这里限制最大是100MB
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 104857600);
            // 限制上传文件的前缀
            // 设置文件夹，这里按照日期分文件夹
            String year = new SimpleDateFormat("yyyy").format(new Date());
            String month = new SimpleDateFormat("MM").format(new Date());
            String day = new SimpleDateFormat("dd").format(new Date());
            String dir = "images/upload/" + year + "/" + month + "/" + day+ "/";
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            // 生成policy
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessId", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

            return AjaxResult.success("获取凭证成功", respMap);

        } catch (Exception e) {
            logger.error("获取凭证失败", e);
        }

        return AjaxResult.error("获取凭证失败", respMap);
    }

    @Override
    public AjaxResult uploadOss(MultipartFile file) {
        if (null == file) {
            return AjaxResult.error();
        }
        try {
            String fileName = file.getOriginalFilename();
            String year = new SimpleDateFormat("yyyy").format(new Date());
            String month = new SimpleDateFormat("MM").format(new Date());
            String day = new SimpleDateFormat("dd").format(new Date());
            String newFileName = UUID.randomUUID().toString() + "_" + fileName;
            String filePath = "images/upload/" + year + "/" + month + "/" + day+ "/" + newFileName;
            String url = ossAddrs + "/" + filePath;
            ossClient.putObject(bucketName, filePath, file.getInputStream());
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", newFileName);
            ajax.put("originalFilename", file.getOriginalFilename());
            logger.info("上传成功:{}", ajax);
            return ajax;
        } catch (Exception e) {
            logger.error("上传失败", e);
        }
        return AjaxResult.error();
    }
}
